﻿#region Header

/**************************************
 * DATE:          19.01.2011 20:44
 * AUTHOR:        Raphael B. Estrada
 * AUTHOR URL:    http://www.galaktor.net
 * AUTHOR E-MAIL: galaktor@gmx.de
 *
 * The MIT License
 *
 * Copyright (c) 2011 Raphael B. Estrada
 * Author URL:    http://www.galaktor.net
 * Author E-Mail: galaktor@gmx.de
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 * ***********************************/

#endregion Header

using System.Collections.Generic;
using ICSharpCode.NRefactory.Ast;
using Typemock.Lint.SDK;

namespace TestLintExtensions
{
    public class ReflectionUsageRule: BaseTestReviewer
    {
        private readonly List<string> reflectionTypes = new List<string> { "methodinfo", "propertyinfo", "constructorinfo", "assembly" };

        public override ReviewCategory DefaultRuleCategory
        {
            get { return ReviewCategory.Other; }
        }
        
        public override object VisitUsingDeclaration(UsingDeclaration usingDeclaration, object data)
        {

            if (usingDeclaration.UsesNamespace("NUnit.Framework") &&
                usingDeclaration.UsesNamespace("System.Reflection"))
            {
                ReviewInfo info = ExpressionHelpers.MakeReviewFromExpression(this,
                                                                             usingDeclaration,
                                                                             ruleUrl:
                                                                                 @"http://www.bobmccune.com/2006/12/09/unit-testing-best-practices/",
                                                                             text:
                                                                                 "It appears that you are using Reflection in test code. This can introduce hard-to-find bugs in your test code and should be avoided at all times.",
                                                                             title: "Reflection in test code");

                Reviews.Add(info);
            }

            return base.VisitUsingDeclaration(usingDeclaration, data);
        }

        

        public override object VisitVariableDeclaration(VariableDeclaration variableDeclaration, object data)
        {
            if (IsInsideTestMethod)
            {
                LocalVariableDeclaration declaration = variableDeclaration.Parent as LocalVariableDeclaration;
                if (declaration != null)
                {
                    string variableType = declaration.TypeReference.Type;
                    if (reflectionTypes.Contains(variableType.ToLowerInvariant()))
                    {
                        ReviewInfo info = ExpressionHelpers.MakeReviewFromExpression(this,
                                                                                     variableDeclaration,
                                                                                     ruleUrl:
                                                                                         "",
                                                                                     text:
                                                                                         "It appears that you are using Reflection in test code. This can introduce hard-to-find bugs in your test code and should be avoided at all times.",
                                                                                     title: "Reflection in test code");

                        Reviews.Add(info);
                    }
                }
            }

            return base.VisitVariableDeclaration(variableDeclaration, data);
        }
    }
}